﻿namespace Webinator.Toolboxes
{
    using System;
    using System.Web.Script.Serialization;
    using Util;

    /// <summary>
    /// Contains useful json functionality.
    /// </summary>
    public static class JsonToolbox
    {
        /// <summary>
        /// Random number generator.
        /// </summary>
        private static readonly Random _randomClass = new Random((int)DateTime.Now.Ticks);

        /// <summary>
        /// Json deserializer.
        /// </summary>
        private static readonly JavaScriptSerializer _serializer;

        /// <summary>
        /// Initializes static members of the <see cref="JsonToolbox"/> class.
        /// </summary>
        static JsonToolbox()
        {
            _serializer = new JavaScriptSerializer();
            _serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
        }

        /// <summary>
        /// Determines whether the specified json is valid.
        /// </summary>
        /// <param name="json">The json.</param>
        /// <returns>
        ///   <c>true</c> if the specified json is valid, otherwise, <c>false</c>.
        /// </returns>
        public static bool IsValidJson(string json)
        {
            if (string.IsNullOrWhiteSpace(json)) return false;

            var valid = true;

            if (!(json.StartsWith("{") || json.StartsWith("[")))
            {
                json = JsonpToJson(json);
            }

            try
            {
                var javaScriptSerializer = new JavaScriptSerializer();
                javaScriptSerializer.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });
                javaScriptSerializer.Deserialize(json, typeof(object));
            }
            catch
            {
                valid = false;
            }

            return valid;
        }

        /// <summary>
        /// Dynamically deserializes the specified json.
        /// </summary>
        /// <param name="json">The json.</param>
        /// <returns>
        /// A dynamic object containing the deserialized json.
        /// </returns>
        public static dynamic DeserializeJson(string json)
        {
            if (string.IsNullOrWhiteSpace(json)) return null;

            if (!(json.StartsWith("{") || json.StartsWith("[")))
            {
                json = JsonpToJson(json);
            }

            return _serializer.Deserialize(json, typeof(object));
        }

        /// <summary>
        /// Converts jsonp to json.
        /// </summary>
        /// <param name="jsonp">The jsonp.</param>
        /// <returns>
        /// The jsonp string converted to json.
        /// </returns>
        public static string JsonpToJson(string jsonp)
        {
            string json;

            try
            {
                json = jsonp.Substring(jsonp.IndexOf('(') + 1);
                json = json.Substring(0, json.LastIndexOf(')'));
            }
            catch
            {
                json = jsonp;
            }
            
            return json;
        }

        /// <summary>
        /// Generates a random callback number.
        /// </summary>
        /// <returns>
        /// A 13 digit callback number.
        /// </returns>
        public static string GenerateCallbackNumber()
        {
            string callback = string.Empty;
            for (int i = 0; i < 13; i++)
            {
                callback += _randomClass.Next(0, 10);
            }

            return callback;
        }
    }
}
